import React, { useEffect, useCallback, useRef, useState } from "react";
import { notification, Spin, Space, Image } from "antd";
import { PlusOutlined } from "@ant-design/icons";
import { ModalForm } from "@ant-design/pro-form";
import update from "immutability-helper";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import "./index.less";

import { uploadImage } from "@/services/goods";
import { uploadRotationImage } from "@/services/banner";
import { uploadCategoryImage } from "@/services/category";

const IMAGE_ENUMS = ["image/jpg", "image/jpeg", "image/png", "image/gif"];
const VIDEO_ENUMS = [
  "video/mp4",
  "video/x-flv",
  "video/flv",
  "video/webm",
  "video/ogg",
];

import DragableUploadListItem from "./DragableUploadListItem";

const UploadFile = ({
  value,
  onChange,
  fileType = 1, // 1=图片 2=视频 3= 图片+视频
  maxCount = 1, // 最大上传数量
  maxSize = 0, // 上传大小限制
  format = null, // 上传格式
  uploadType = 1, // TODO 区分上传接口
}) => {
  const uploadFunc = {
    1: uploadImage,
    2: uploadRotationImage,
    3: uploadCategoryImage,
  };

  // 图片 默认格式和大小
  if (fileType === 1) {
    format = format || IMAGE_ENUMS;
    maxSize = maxSize || 5;
  }

  // 视频 默认格式和大小
  if (fileType === 2) {
    format = format || VIDEO_ENUMS;
    maxSize = maxSize || 20;
  }

  // 图片 + 视频 默认格式和大小
  if (fileType === 3) {
    format = format || [...IMAGE_ENUMS, ...VIDEO_ENUMS];
    maxSize = maxSize || 10;
  }

  const acceptStr = format.map((item) => "." + item.split("/")[1]).join(",");
  const fileRef = useRef(null);
  const [uploading, setUploading] = useState(false);
  const [visible, setVisible] = useState(false); // 图片预览
  const [currentIndex, setCurrentIndex] = useState(0); // 当前图片下标

  const [visibleVideo, setVisibleVideo] = useState(false); // 视频预览
  const [currentSrc, setCurrentSrc] = useState(false); // 当前视频url

  const [fileList, setFileList] = useState([
    // {
    //   uid: '-1',
    //   name: 'image1.png',
    //   status: 'done',
    //   url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    // },
  ]);

  useEffect(() => {
    setFileList(() => {
      if (value) {
        if (typeof value === "string") {
          return value ? [{ url: value }] : []; // 单个时初始化
        } else {
          return value; // 多个时 数组
        }
      } else {
        return [];
      }
    });
  }, [value]);

  // 从选择的文件中过滤出符合格式和大小的文件列表和不符合的
  const getOkOrNotFiles = (arr) => {
    let notMaxSize = []; // 不符合大小的
    let notFormat = []; // 不符合格式的
    const oks = arr.filter((file) => {
      const isFormatFile = format.includes(file.type);
      const isMaxSize = file.size / 1024 / 1024 < maxSize;
      if (isFormatFile && isMaxSize) {
        return file;
      }
      if (!isMaxSize) {
        notMaxSize.push(file);
      }
      if (!isFormatFile) {
        notFormat.push(file);
      }
    });

    return [oks, notMaxSize, notFormat];
  };

  // 文件格式错误提示
  const setTip = (notMaxSize, notFormat) => {
    let notFormatStr = "";
    let notMaxSizeStr = "";
    if (notFormat.length) {
      const fileNames = notFormat.map((item) => item.name).join(",");
      notFormatStr = `【${fileNames}】文件格式错误`;
    }
    if (notMaxSize.length) {
      const fileNames = notMaxSize.map((item) => item.name).join(",");
      notMaxSizeStr = `【${fileNames}】文件大小超过${maxSize}M`;
    }

    let tip = "";
    if (notFormatStr) {
      tip += notFormatStr + ",";
    }
    if (notMaxSizeStr) {
      tip += notMaxSizeStr;
    }
    if (tip) {
      tip += ",请重新上传!";
      notification.error({
        message: "错误提示",
        description: tip,
      });
    }
  };

  // 上传请求接口
  const asyncUpload = (files) => {
    return new Promise((resolve, reject) => {
      const oldLength = fileList.length; // 已经上传了的
      const needUploadFiles = Array.from(files).slice(0, maxCount - oldLength); // 超过max的就截掉
      const [okFiles, notMaxSize, notFormat] = getOkOrNotFiles(needUploadFiles);
      setTip(notMaxSize, notFormat);

      if (!okFiles.length) return;
      let arr = [];
      setUploading(true);
      okFiles.forEach(async (file) => {
        const formData = new FormData();
        formData.append("file", file);
        const res = await uploadFunc[uploadType](formData);
        arr.push({ url: res.data });
        // 符合要求上传的数量===上传成功的数量 就返回成功列表
        if (okFiles.length === arr.length) {
          setUploading(false);
          resolve(arr);
        }
      });
    });
  };

  // 上传
  const fileUpload = async () => {
    const files = fileRef.current.files;
    let arr = await asyncUpload(files);
    if (maxCount === 1) {
      setFileList(arr);
      onChange(arr[0].url); // 只能上传一个时直接返回 url
    } else {
      setFileList([...fileList, ...arr]);
      onChange([...fileList, ...arr]); // 多个时返回：[{url:'xx.png'}]
    }
  };

  // 移动排序
  const moveRow = useCallback(
    (dragIndex, hoverIndex) => {
      const dragRow = fileList[dragIndex];
      const afterList = update(fileList, {
        $splice: [
          [dragIndex, 1],
          [hoverIndex, 0, dragRow],
        ],
      });
      setFileList(afterList);
      onChange(afterList);
    },
    [fileList]
  );

  // 删除
  const handleRemove = (index) => {
    fileList.splice(index, 1);
    setFileList([...fileList]);
    onChange([...fileList]);
  };

  // 预览
  const handelPreview = (index, fileType) => {
    if (fileType === 1) {
      setCurrentIndex(index);
      setVisible(true);
    }
    if (fileType === 2) {
      setCurrentSrc(fileList[index].url);
      setVisibleVideo(true);
    }
  };

  return (
    <DndProvider backend={HTML5Backend}>
      <Spin spinning={uploading}>
        <Space size={fileList.length ? "small" : 0}>
          {fileList.map((file, index) => (
            <DragableUploadListItem
              key={file.url}
              file={file}
              fileType={fileType}
              moveRow={moveRow}
              index={index}
              handleRemove={handleRemove}
              handelPreview={handelPreview}
              IMAGE_ENUMS={IMAGE_ENUMS}
              VIDEO_ENUMS={VIDEO_ENUMS}
            />
          ))}

          {/* 图片预览 */}
          <div style={{ display: "none" }}>
            <Image.PreviewGroup
              preview={{
                current: currentIndex,
                visible,
                onVisibleChange: (vis) => setVisible(vis),
              }}
            >
              {fileList.map((item, index) => (
                <Image src={item.url} key={index}></Image>
              ))}
            </Image.PreviewGroup>
          </div>

          {/* 视频预览 */}
          <ModalForm
            visible={visibleVideo}
            onVisibleChange={setVisibleVideo}
            submitter={false}
          >
            <div
              style={{
                display: "flex",
                justifyContent: "center",
                alignItems: "center",
              }}
            >
              <video controls src={currentSrc}></video>
            </div>
          </ModalForm>

          {/* 使用原生input 进行获取文件列表实现多个上传 */}
          {fileList.length < maxCount && (
            <div className="add">
              <PlusOutlined className="icon" />
              <input
                accept={acceptStr}
                className="add-input"
                ref={fileRef}
                type="file"
                multiple={maxCount > 1}
                onChange={fileUpload}
                // directory
              />
            </div>
          )}
        </Space>
      </Spin>
    </DndProvider>
  );
};

export default UploadFile;
